package com.example.arithmetic.round;

import org.springframework.boot.json.JsonParser;

import java.math.BigDecimal;
import java.util.Random;

import static java.math.BigDecimal.ROUND_HALF_UP;


public class RoundUtils {
    /*坐标的原点*/
    private static final double COORDS_ORIGIN = 0.00D;
    /*把圆千等分*/
    private static final int ROUND_THOUSANDS = 1000;
    /*信号强度比例尺
    * 100信号强度相当于1米
    * */
    private static final double SIGNAL_INTENSITY_SCALE = 100D;

    private static final int ANGLE_0 = 0;
    private static final int ANGLE_90 = 90;
    private static final int ANGLE_180 = 180;
    private static final int ANGLE_270 = 270;
    private static final int ANGLE_360 = 360;

    /**
     * 圆心坐标：(x0,y0)
     *
     * 半径：r
     *
     * 角度：a
     *
     * 则圆上任一点为：（x1,y1）
     *
     * x1 = x0 + r * cos( a )
     *
     * y1 = y0 + r * sin( a )
     *
     * PS:在Java里面 Math.sin(double radians) ，radians是弧度，使用Math.toRadians(double angdeg)先把角度转换成弧度再计算；
     *
     * @param roundCenter
     * @param radius
     * @return
     */
    public static CoordinatesDTO getRandomRoundCoordinates(CoordinatesDTO roundCenter,int radius){
        double i = Math.floor(Math.random()*360);
        double x = (roundCenter.getX() + radius * Math.cos(Math.toRadians(i)));
        double y = (roundCenter.getY() + radius * Math.sin(Math.toRadians(i)));
        return new CoordinatesDTO(x,y);
    }

    /**
     * 获取园上的点的坐标
     * @param roundCenter 圆心的坐标
     * @param radius 园的半径
     * @param angle 园的半径和圆心的角度
     * @return
     */
    /*public static CoordinatesDTO getRoundCoordinates(CoordinatesDTO roundCenter,double radius, double angle){
        double x = (roundCenter.getX() + radius * Math.cos(angle*Math.PI/180));
        double y = (roundCenter.getY() + radius * Math.sin(angle*Math.PI/180));
        return new CoordinatesDTO(x,y);
    }

    public static CoordinatesDTO getRoundCoordinates2(CoordinatesDTO roundCenter,double radius, double angle){
        double x = (roundCenter.getX() - radius * Math.sin(Math.PI * (angle - 90) / 180));
        double y = (roundCenter.getY() - radius - 10 + radius * Math.cos(Math.PI * (angle - 90) / 180));
        return new CoordinatesDTO(x,y);
    }*/


    public static CoordinatesDTO getRoundCoordinates4(CoordinatesDTO roundCenter,double radius, int angle){
        if(angle <= ANGLE_0 || angle > ANGLE_360){
            //抛出越界异常
            return null;
        }
        /*0 < angle <=90*/
        if(angle <= ANGLE_90){
            double x = (roundCenter.getX() + radius * Math.sin(Math.toRadians(ANGLE_90 - angle)));
            double y = (roundCenter.getY() + radius * Math.cos(Math.toRadians(ANGLE_90 - angle)));
            return new CoordinatesDTO(scaleDecimal(x),scaleDecimal(y));
        }
        /*90< angle <= 180*/
        if(angle <= ANGLE_180){
            double x = (roundCenter.getX() - radius * Math.cos(Math.toRadians(ANGLE_180 - angle)));
            double y = (roundCenter.getY() + radius * Math.sin(Math.toRadians(ANGLE_180 - angle)));
            return new CoordinatesDTO(scaleDecimal(x),scaleDecimal(y));
        }
        /*180 < angle <= 270*/
        if(angle <= ANGLE_270){
            double x = (roundCenter.getX() - radius * Math.sin(Math.toRadians(ANGLE_270 - angle)));
            double y = (roundCenter.getY() - radius * Math.cos(Math.toRadians(ANGLE_270 - angle)));
            return new CoordinatesDTO(scaleDecimal(x),scaleDecimal(y));
        }
        /*270 < angle <= 360*/
        double x = (roundCenter.getX() + radius * Math.cos(Math.toRadians(ANGLE_360 - angle)));
        double y = (roundCenter.getY() - radius * Math.sin(Math.toRadians(ANGLE_360 - angle)));
        return new CoordinatesDTO(scaleDecimal(x),scaleDecimal(y));
    }

    public static CoordinatesDTO getRoundCoordinates5(CoordinatesDTO roundCenter,double radius){
        Double x = roundCenter.getX();

        double a = (x - radius) + (randomNum(0,1000) / 1000) * 2 * radius;
        BigDecimal aDecimal = new BigDecimal(String.valueOf(a));
        a = aDecimal.setScale(2,BigDecimal.ROUND_HALF_DOWN).doubleValue();

        double b = roundCenter.getY() - sqrt(radius*radius - (x-a)*(x-a));
        BigDecimal bDecimal = new BigDecimal(String.valueOf(b));
        b = bDecimal.setScale(2,BigDecimal.ROUND_HALF_DOWN).doubleValue();

        return new CoordinatesDTO(a,b);
    }

    public static double scaleDecimal(double value){
        BigDecimal bDecimal = new BigDecimal(String.valueOf(value));
        return bDecimal.setScale(2,BigDecimal.ROUND_HALF_DOWN).doubleValue();
    }


    /*public static CoordinatesDTO getRoundCoordinates6(CoordinatesDTO roundCenter,double radius){
        BigDecimal xDecimal = new BigDecimal(roundCenter.getX());
        BigDecimal radiusDecimal = new BigDecimal(radius);
        BigDecimal xSubRadis = xDecimal.subtract(radiusDecimal);
        BigDecimal random = new BigDecimal(Math.random());
        BigDecimal randomX = random.multiply(new BigDecimal(2)).multiply(radiusDecimal);
        BigDecimal aDecimal = xSubRadis.add(randomX);

        BigDecimal yDecimal = new BigDecimal(roundCenter.getY());

        BigDecimal xSubA = xDecimal.subtract(aDecimal);
        BigDecimal xMultX = xSubA.multiply(xSubA);
        BigDecimal subtract = radiusDecimal.multiply(radiusDecimal).subtract(xMultX);
        double sqrt = sqrt(subtract.doubleValue());
        BigDecimal sqrtDecimal = new BigDecimal(sqrt);

        BigDecimal bDecimal = yDecimal.subtract(sqrtDecimal);

        return new CoordinatesDTO(aDecimal.setScale(2,BigDecimal.ROUND_UP).doubleValue(),bDecimal.setScale(2,BigDecimal.ROUND_UP).doubleValue());
    }*/

    /*public static CoordinatesDTO getRoundCoordinates7(CoordinatesDTO roundCenter,double radius){
        *//*获取到圆上的随机数，保留小数点后两位*//*
        BigDecimal randomDecimal = BigDecimal.valueOf(randomNumDivide(0, ROUND_THOUSANDS)).setScale(2, BigDecimal.ROUND_HALF_DOWN);

        BigDecimal xDecimal = BigDecimal.valueOf(roundCenter.getX());
        BigDecimal radiusDecimal = new BigDecimal(radius);
        BigDecimal xSubR = xDecimal.subtract(radiusDecimal);
        BigDecimal diameterDecimal = radiusDecimal.add(radiusDecimal);
        BigDecimal randomDiameter = randomDecimal.multiply(diameterDecimal);
        BigDecimal aDecimal = randomDiameter.add(xSubR);

        BigDecimal radiusSquare = radiusDecimal.multiply(radiusDecimal);
        BigDecimal xSubA = xDecimal.subtract(aDecimal);
        BigDecimal xSubASquare = xSubA.multiply(xSubA);
        BigDecimal ySubBSqrt = sqrt(radiusSquare.subtract(xSubASquare), 2);
        BigDecimal yDecimal = BigDecimal.valueOf(roundCenter.getY());
        BigDecimal bDecimal = yDecimal.subtract(ySubBSqrt);
        return new CoordinatesDTO(aDecimal.doubleValue(),bDecimal.doubleValue());
    }*/

    public static double sqrt(double m){
        int num = new Random().nextBoolean() ? 1 : 0 ;
        double sqrt = Math.sqrt(m);
        if(num == 0){
            return sqrt;
        }
        return - sqrt;
    }

    public static BigDecimal sqrt(BigDecimal num, final int scale) {
        BigDecimal x0 = new BigDecimal("0");
        BigDecimal x1 = BigDecimal.valueOf(sqrt(num.doubleValue()));
        while (!x0.equals(x1)) {
            x0 = x1;
            x1 = num.divide(x0, scale, ROUND_HALF_UP);
            x1 = x1.add(x0);
            x1 = x1.divide(new BigDecimal(2), scale, ROUND_HALF_UP);
        }
        return x1;
    }

    public static double randomNumDivide(double min, double max){
        return randomNum(min,max)/max;
    }
    /**
     * 求平均数
     * @param max
     * @param min
     * @return
     */
    public static double randomNum(double min, double max){
        return Math.floor(Math.random()*(max-min+1) + min);
    }

    /**
     * 比例尺转换
     * @param signalIntensity
     * @param scale
     * @return
     */
    public static Double scale(Double signalIntensity,Double scale){
        if(signalIntensity == null){
            return null;
        }
        if(scale == null){
            scale = SIGNAL_INTENSITY_SCALE;
        }
        if(scale == 0.0D){
            return signalIntensity;
        }
        return signalIntensity/scale;
    }

    public static Double scale(Double signalIntensity){
        if(signalIntensity == null){
            return null;
        }
        return signalIntensity/SIGNAL_INTENSITY_SCALE;
    }

    /**
     * 角度的循环算法
     * @param angle 原始角度
     * @param randomAngle 随机的角度，在原始角度的基础上+/- 多少度
     * @return
     */
    public static int angleOperation(int angle, int randomAngle){
        int newAngle = (angle+randomAngle + ANGLE_360) % ANGLE_360;
        if(newAngle == 0){
            return ANGLE_360;
        }
        return newAngle;
    }

    public static void main(String[] args) {
        /*for (int i=0;i<10000000;i++){
            double d = randomNumDivide(0,1000) * 2 * 5 ;
            if(d == 0D){
                System.out.println("最小的："+d);
            }
            if(d == 10D){
                System.out.println("最大的："+d);
            }
            if (d< 0 || d > 10){
                System.out.println("错误的："+d);
            }
            System.out.println(d);
        }*/

        /*for (int i=0;i<100;i++){
            System.out.println(randomNum(-2,2));
        }*/

        //System.out.println(scale(560D,0.0D));

        int angle = (int)randomNum(1, 360);
        /*for (int i=0;i<100;i++){
            int randomAngle = (int)randomNum(-2, 2);
            int newAngle = angleOperation((int)angle, randomAngle);
            System.out.println("angle:"+angle+" randomAngle:"+randomAngle+" newAngle:"+newAngle);
            angle = newAngle;
        }*/
        for (int i=0;i<100;i++){
            /*CoordinatesDTO randomRoundCoordinates = getRoundCoordinates5(new CoordinatesDTO(0D, 5D), 5D);
            System.out.print("x:"+randomRoundCoordinates.getX());
            System.out.println(" y:"+randomRoundCoordinates.getY());*/
            int randomAngle = (int)randomNum(-2, 2);
            int newAngle = angleOperation((int)angle, randomAngle);
            CoordinatesDTO coordinatesDTO = new CoordinatesDTO((double)i, 5D);
            CoordinatesDTO roundCoordinates4 = getRoundCoordinates4(coordinatesDTO, 5D, newAngle);
            double r = (roundCoordinates4.getX()-coordinatesDTO.getX())*(roundCoordinates4.getX()-coordinatesDTO.getX()) + (roundCoordinates4.getY()-coordinatesDTO.getY())*(roundCoordinates4.getY()-coordinatesDTO.getY());
            System.out.println("x:" + roundCoordinates4.getX() + " y:"+roundCoordinates4.getY() +" r:" +scaleDecimal(r));
        }

    }
}
